/*
 * BOWScene.cpp
 *
 *  Created on: Jan 8, 2014
 *      Author: thanhkm
 */

#include "BOWScene.h"

BOWScene::BOWScene() {
}

BOWScene::~BOWScene() {
}

void BOWScene::cluster(std::vector<cv::Mat> vecDescriptors, int dictionarySize){
	//Construct BOWKMeansTrainer
	//define Term Criteria
	cv::TermCriteria tc(CV_TERMCRIT_ITER,100,0.001);
	//retries number
	int retries=1;
	//necessary flags
	int flags=cv::KMEANS_PP_CENTERS;
	//Create the BoW (or BoF) trainer
	cv::BOWKMeansTrainer bowTrainer(dictionarySize,tc,retries,flags);

	for (uint i = 0; i < vecDescriptors.size(); i++){
		bowTrainer.add(vecDescriptors[i]);
	}
	//cluster the feature vectors
	dictionary = bowTrainer.cluster();
}

void BOWScene::computeHistogram(std::vector<cv::Mat> images,
						 cv::Mat &mHistograms, cv::Mat dictionary){

	//create a nearest neighbor matcher
	cv::Ptr<cv::DescriptorMatcher> matcher(new cv::FlannBasedMatcher);
	//create Sift descriptor extractor
	cv::Ptr<cv::DescriptorExtractor> extractor(new cv::SiftDescriptorExtractor);
	//create BoF (or BoW) descriptor extractor
	cv::BOWImgDescriptorExtractor bowDE(extractor,matcher);
	//create Sift feature point extracter
	cv::Ptr<cv::FeatureDetector> detector(new cv::SiftFeatureDetector());

	//Set the dictionary with the vocabulary we created in the first step
	bowDE.setVocabulary(dictionary);

	// first: detect the SIFT keypoints of image
	// then: compute its histogram following the dictionary
	cv::Mat histogram;
	std::vector<cv::Mat> vecHistograms;
	std::vector<cv::KeyPoint> keypoints;
	for (uint i = 0; i < images.size(); i++){
		detector->detect(images[i], keypoints);
//std::cout << " number of keypoints :" << keypoints.size() << " ";
		//extract BoW (or BoF) descriptor from given image
		bowDE.compute(images[i], keypoints, histogram);
//std::cout << histogram.col(0) << std::endl;
		vecHistograms.push_back(histogram);
	}

	//convert vector of histograms to cv::Mat
	int histogramsSize = vecHistograms.size();
	int histogramsCols = vecHistograms[0].cols;
std::cout << vecHistograms[0].rows <<" " << histogramsCols << std::endl;
std::cout << histogramsSize << std::endl;
	mHistograms = cv::Mat(histogramsSize, histogramsCols, CV_32FC1);
	for (int i = 0; i < histogramsSize; i++){
		for (int d = 0; d < histogramsCols; d++) {
			mHistograms.at<float>(i, d) = vecHistograms[i].at<float>(0,d);
		}
	}
//	std::cout << mHistograms.row(0) << std::endl << vecHistograms[0].row(0) << std::endl;
}

void BOWScene::setDictionary(cv::Mat dict){
	dictionary = dict;
}

cv::Mat BOWScene::getDictionary(){
	return dictionary;
}
